#首先需要分析详情页面，功能，从上到下，从左到右逐一实现功能

from flask_restful import Resource,fields,marshal,inputs
from flask import abort,current_app
from flask import g,request
from flask_restful.reqparse import RequestParser
from pymysql import IntegrityError

from models.news import Article,Attitude,Collection
from models.user import Relation
from cache.user import UserProfileCache,RelationCache,UserArticleAttitudeCache,UserArticleCollectionsCache,UserReadingHistoreStorage
from cache.article import ArticleDetailCache
from toutiao.utils.decorators import Loginrequired
from toutiao import db
from cache.comment import ArticleCommentCache
from toutiao.apps.home import constants

article_fields = {
    'art_id': fields.Integer(attribute='id'),
    'title': fields.String(attribute='title'),
    'pubdate': fields.DateTime(attribute='ctime', dt_format='iso8601'),
    'content': fields.String(attribute='content.content'),
    'aut_id': fields.Integer(attribute='user_id'),
    'ch_id': fields.Integer(attribute='channel_id'),
}
#attribute指定模型字段和要返回的字典，flask序列化器优点之一
#详情页面展示,查询文章作者信息
class DetailResource(Resource):

    def get(self,article_id):
        '''
        获取文章id
        根据id查询文章详细信息
        查询文章作者信息
        初始化　是否关注，收藏，喜欢，不喜欢
        返回相应
        :return:
        '''
        #根据文章id查询文章
        # article = Article.query.filter(Article.id==article_id,
        #                                Article.status==Article.STATUS.APPROVED).first()
        # if article is None:
        #     abort(404)
        #
        # article_dict = marshal(article,article_fields)
        # #获取作者信息
        # user = UserProfileCache(article_dict.get('aut_id')).get()
        # article_dict['aut_name'] = user['name']
        # article_dict['aut_photo'] = user['photo']

        #使用缓存实现
        article_dict = ArticleDetailCache(article_id).get()

        #初始化　是否关注，收藏，喜欢，不喜欢
        is_followed = False   #关注
        attitude = None       #喜欢
        is_collected = False  # 收藏

        #添加文章态度的缓存，首先判断用户是否登录
        if g.user_id:
            # try:
            #     attitudes = UserArticleAttitudeCache(g.user).get_all()
            # except Exception as e:
            #     current_app.logger.error(e)
            # else:
            #     attitude = attitudes.get(int(article_id))
            #上面为调用查询所有文章态度，再查询某个文章态度，以上两步封装为缓存中查询某个文章态度的方法
            attitude = UserArticleAttitudeCache(g.user_id).get_article_attitude(article_id)

            #判断用户是否收藏
            is_collected = UserArticleCollectionsCache(g.user_id).user_collect_target(article_id)

            # 添加阅读历史(浏览了这篇文章，就把这篇文章id：时间戳　添加到阅读历史的缓存中)
            UserReadingHistoreStorage(g.user_id).save(article_id)

            #判断登录用户我是否关注了这篇文章的作者
            from cache.user import UserFollowingCache
            is_followed = UserFollowingCache(g.user_id).user_follows_target(article_dict.get('aut_id'))


        article_dict['is_followed'] = is_followed
        article_dict['attitude'] = attitude
        article_dict['is_collected'] = is_collected

        return article_dict


#关注用户
class FollowResource(Resource):

    method_decorators = {'post':[Loginrequired]}

    def post(self):
        #已登录用户id
        user_id = g.user_id
        # 关注用户id（数据在请求体中）
        # try:
        #     target = request.json.get('target')
        # except Exception as e:
        #     return {'message':'缺少信息'},404
        # 验证数据(正确的验证方式)
        parser = RequestParser()
        parser.add_argument('target',location='json',required=True)
        args = parser.parse_args()
        target = args.get('target')

        try:
            user = UserProfileCache(target).get()
        except Exception as e:
            current_app.logger.error(e)

        if user is None:
            return {'message':'没有这个人'},400

        # 查询数据库修改关注状态(以下错误，应先查询有没有这个人，插入数据，而不是更新数据)
        # relation = Relation.query.filter_by(user_id=user_id).first()
        # relation.query.filter(Relation.target_user_id==target).update({'relation':Relation.RELATION.FOLLOW})
        # db.session.commit()
        # 数据入库(正确)
        # relation = Relation()
        # relation.user_id = g.user_id
        # relation.target_user_id = target
        # relation.relation = Relation.RELATION.FOLLOW
        # db.session.add(relation)
        # db.session.commit()
        #再次更新逻辑，应先查询有没有这个人，没有，插入数据，有，更新数据
        relation = Relation.query.filter(Relation.user_id == user_id,
                                   Relation.target_user_id == target).first()
        if not relation:
            relation=Relation()
            relation.user_id=user_id
            relation.target_user_id = target
            db.session.add(relation)   #添加数据必须db.session.add(模型)再commit
        relation.relation = Relation.RELATION.FOLLOW
        db.session.commit()
        #关注添加到缓存，缓存操作由于是集合，添加删除即可，无需判断有无查找保存
        RelationCache(user_id).add(target)

        #post成功,返回201
        return {'target':target},201

    #数据缓存选择，列表，集合，有序集合，其中有序集合最合适（不重复，根据权重表示先后顺序）
    #sort sets有序集合一般用时间戳作为权重，时间戳为1970-1-1到现在的一个秒数

    #获取用户关注列表GET /app/v10/user/followings?page=xxx&per_page=xxx
    def get(self):
        parser = RequestParser()
        parser.add_argument('page',type=inputs.positive,required=False,location='args')
        parser.add_argument('per_page',type=inputs.int_range(constants.DEFAULT_USER_FOLLOWINGS_PER_PAGE_MIN,
                                                             constants.DEFAULT_USER_FOLLOWINGS_PER_PAGE_MAX,
                                                             'per_page'),
                            required=False,location='args')
        args=parser.parse_args()
        page = 1 if args.page is None else args.page
        per_page = args.per_page if args.per_page else constants.DEFAULT_USER_FOLLOWINGS_PER_PAGE_MIN

        followers = Relation.query.filter_by(user_id=g.user_id,
                                             relation=Relation.RELATION.FOLLOW).order_by(Relation.utime.desc()).all()
        total_count = len(followers)

        #获取我关注的所有人的id列表
        # follower_ids=[]
        # for relation in followers:
        #     follower_ids.append(relation.target_user_id)

        #缓存获取我关注的所有人的列表
        from cache.user import UserFollowingCache
        follower_ids=UserFollowingCache(g.user_id).get()
        total_count=len(follower_ids)

        # 先获取分页数据，遍历获取缓存信息
        page_followings = follower_ids[(page - 1) * per_page:page * per_page]

        results = []
        # 获得的时登录的我关注的用户，判断一下他有没有关注我,即他是不是我的粉丝,
        # 下面获取我的粉丝列表
        from cache.user import UserFansCache
        fans = UserFansCache(g.user_id).get()

        for following_user_id in page_followings:
            user = UserProfileCache(following_user_id).get()

            results.append({
                'id': following_user_id,
                'name': user.get('name'),
                'photo': user.get('photo'),
                'mutual_follow': user.get('id') in fans
            })

        return {'total_count': total_count, 'page': page, 'per_page': per_page, 'results': results}



class FollowingDeleteResource(Resource):

    method_decorators = [Loginrequired]

    def delete(self,target):
        '''
        接收数据：target是用户取消关注的id
        验证数据
        标记数据库，删除缓存
        返回相应
        :param target:
        :return:
        '''
        user_id = g.user_id
        #修改数据库用update
        Relation.query.filter(Relation.user_id == user_id,
                              Relation.target_user_id == target).update({'relation':Relation.RELATION.DELETE})
        db.session.commit()
        #调用清除缓存
        RelationCache(user_id).delete(target)
        return target

"""
Attitude
    attitude = None 没任何态度
    attitude = 1    点赞
    attitude = 0    不喜欢

"""
#点赞
class AttitudeLikingResource(Resource):
    method_decorators = [Loginrequired]

    def post(self):
        #谁点赞
        user_id = g.user_id
        parser = RequestParser()
        parser.add_argument('target',location='json',required=True,type=inputs.positive)
        args = parser.parse_args()
        #点赞的哪篇文章
        target = args.get('target')
        #查询数据库
        attitude = Attitude.query.filter(Attitude.user_id==user_id,
                                         Attitude.article_id==target).first()
        #没有新增态度
        if attitude is None:
            attitude = Attitude(
                user_id = user_id,
                article_id = target,
                attitude = Attitude.ATTITUDE.LIKING
            )
            db.session.add(attitude)
        else:
            # 有，修改态度
            attitude.attitude=Attitude.ATTITUDE.LIKING
        db.session.commit()
        #修改数据库后组要修改缓存，删除全部，部分，更新值三种方法最终采取更新
        UserArticleAttitudeCache(user_id).update_field(target,Attitude.ATTITUDE.LIKING)

        return {'target':target},201


#取消点赞
class AttitudeLikeDeleteResource(Resource):

    method_decorators = [Loginrequired]

    def delete(self,target):
        user_id = g.user_id
        attitude = Attitude.query.filter(Attitude.user_id==user_id,
                                         Attitude.article_id==target).update({'attitude':Attitude.ATTITUDE.DISLIKE})
        db.session.commit()
        #由于数据库不能保存不状态的none，所以状态可以选择缓存为－１,此时与数据库并不冲突
        UserArticleAttitudeCache(user_id).update_field(target, -1)

        return {'message':'OK'},204


#不喜欢此篇文章
class DislikeResource(Resource):
    method_decorators = [Loginrequired]

    def post(self):
        #谁点赞
        user_id = g.user_id
        #点赞的文章id
        parser = RequestParser()
        parser.add_argument('target',location='json',required=True,type=inputs.positive)
        args = parser.parse_args()
        target = args.get('target')
        #查找数据库
        atti=Attitude.query.filter(Attitude.user_id==user_id,
                              Attitude.article_id==target).first()

        if not atti:
            # 没有添加
            atti=Attitude.add(
                user_id=user_id,
                article_id=target,
                attitude=Attitude.ATTITUDE.DISLIKE
            )
            db.session.add(atti)
        else:
            # 有，修改
            atti.attitude=Attitude.ATTITUDE.DISLIKE

        db.session.commit()

        UserArticleAttitudeCache(user_id).claer()
        return {'target':target},201


#取消不喜欢
class DislikeDeleteResource(Resource):

    method_decorators = [Loginrequired]

    def delete(self,target):
        Attitude.query.filter_by(user_id=g.user_id,
                                 article_id=target,
                                 attitude=Attitude.ATTITUDE.DISLIKE).update({'attitude': None})
        db.session.commit()

        UserArticleAttitudeCache(g.user_id).claer()
        return {'message': 'OK'}, 204


#收藏文章,前端点击收藏后会刷新页面，所以看不到效果，走断点检查即可
class UserCollectionResource(Resource):
    method_decorators = [Loginrequired]

    def post(self):
        '''
        接收json数据，parser验证
        查询数据库是否存在，存在，修改用户收藏表的is_delete的标记，
        　　　　　　　　　　不存在，新增
        :return:
        '''
        user_id = g.user_id
        parser = RequestParser()
        parser.add_argument('target',location='json',type=inputs.positive,required=True)
        args = parser.parse_args()
        target = args.get('target')

        #查询，更新或添加数据库方式一
        # collection = Collection.query.filter(Collection.user_id==user_id,
        #                         Collection.article_id==target).first()
        # if collection is None:
        #     collection=Collection()
        #     collection.user_id=user_id
        #     collection.article_id=target
        #     collection.is_deleted=False
        #     db.session.add(collection)
        # else:
        #     collection.is_deleted=False
        # db.session.commit()

        # 查询，更新或添加数据库方式二,默认值is_deleted=False
        try:
            collection = Collection(user_id=user_id,article_id=target)
            db.session.add(collection)
            db.session.commit()
        except IntegrityError:
            db.session.rollback()
            Collection.query.filter_by(user_id=g.user_id, article_id=target, is_deleted=True) \
                .update({'is_deleted': False})
            db.session.commit()
        #清除收藏的缓存
        UserArticleCollectionsCache(g.user_id).clear()
        return {'target':target},201

    #获取用户收藏列表
    def get(self):
        parser = RequestParser()
        parser.add_argument('page',type=inputs.positive,
                            required = False,
                            location = 'args')
        parser.add_argument('per_page',type=inputs.int_range(constants.DEFAULT_COMMENT_PER_PAGE_MIN,
                                                             constants.DEFAULT_COMMENT_PER_PAGE_MAX,
                                                             'per_page'),
                            required = False,location = 'args')
        args = parser.parse_args()
        page = 1 if args.page is None else args.page
        per_page = args.per_page if args.per_page else constants.DEFAULT_COMMENT_PER_PAGE_MIN
        # #查看用户收藏的所有文章
        # collections = Collection.query.filter_by(user_id = g.user_id,
        #                                          is_deleted = False).order_by(Collection.utime.desc()).all()
        # #长度就是收藏文章的数量
        # total_count = len(collections)
        # #列表保存用户收藏的所有文章id
        # collections_ids = []
        #
        # for collection in collections:
        #     collections_ids.append(collection.article_id)
        # #切片获取指定页的数据，第一页，获取[0:10]，第二页[11:20],第n页[ (n-1)*10 : n*10 ]　切片包括前面不包括后面
        # page_articles = collections_ids[(page-1)*per_page:page*per_page]

        #使用缓存实现
        total_count,page_articles = UserArticleCollectionsCache(g.user_id).get_page(page,per_page)

        result = []
        for article_id in page_articles:
            #调用文章详细信息缓存，返回的是文章详细信息的字典
            article = ArticleDetailCache(article_id).get()
            #文章字典添加上，用户对这篇文章的态度，调用态度缓存
            article['is_liking'] = UserArticleAttitudeCache(g.user_id).get_article_attitude(article_id)
            #把所有文章的字典，放在一个列表中
            result.append(article)

        return {'total_count': total_count, 'page': page, 'per_page': per_page, 'results': result}


#取消收藏文章
class UserCollectDeleteResource(Resource):
    method_decorators = [Loginrequired]
    def delete(self,target):

        Collection.query.filter(Collection.user_id == g.user_id,
                                Collection.article_id == target).update({'is_deleted':True})
        db.session.commit()
        UserArticleCollectionsCache(g.user_id).clear()

        return {'message':'ok'},204


# 阅读历史
class ReadingHistoryResource(Resource):

    method_decorators = [Loginrequired]

    # 分页获取用户的阅读历史，分页数据前端传来，需要验证
    def get(self):
        parser = RequestParser()
        parser.add_argument('page',type=inputs.positive,
                            required = False,
                            location = 'args')
        parser.add_argument('per_page',type=inputs.int_range(constants.DEFAULT_COMMENT_PER_PAGE_MIN,
                                                             constants.DEFAULT_COMMENT_PER_PAGE_MAX,
                                                             'per_page'),
                            required=False,location='args')
        args = parser.parse_args()
        page = 1 if args.page is None else args.page
        per_page = args.per_page if args.per_page else constants.DEFAULT_COMMENT_PER_PAGE_MIN

        user_id = g.user_id
        results = []
        total_count, article_ids = UserReadingHistoreStorage(user_id).get(page, per_page)

        for article_id in article_ids:
            article = ArticleDetailCache(int(article_id)).get()
            article['is_liking'] = UserArticleAttitudeCache(g.user_id).get_article_attitude(article_id)
            results.append(article)

        return {'total_count': total_count, 'page': page, 'per_page': per_page, 'results': results}



#获取用户粉丝列表，谁关注了我，别人的target_user_id 是登录用户我的id
class FansResource(Resource):
    method_decorators = [Loginrequired]

    def get(self):
        """
        获取关注的用户列表
        """
        # 参数验证
        qs_parser = RequestParser()
        qs_parser.add_argument('page', type=inputs.positive, required=False, location='args')
        qs_parser.add_argument('per_page', type=inputs.int_range(constants.DEFAULT_USER_FOLLOWINGS_PER_PAGE_MIN,
                                                                 constants.DEFAULT_USER_FOLLOWINGS_PER_PAGE_MAX,
                                                                 'per_page'),
                               required=False, location='args')
        args = qs_parser.parse_args()
        page = 1 if args.page is None else args.page
        per_page = args.per_page if args.per_page else constants.DEFAULT_USER_FOLLOWINGS_PER_PAGE_MIN

        # 查询结果
        # followers = Relation.query.filter_by(target_user_id=g.user_id,
        #                                      relation=Relation.RELATION.FOLLOW) \
        #     .order_by(Relation.utime.desc()).all()
        #
        # total_count = len(followers)
        #
        # # 获取所有的关注人员id
        # follower_ids = []
        # for relation in followers:
        #     follower_ids.append(relation.user_id)

        # 使用缓存实现
        from cache.user import UserFansCache
        follower_ids = UserFansCache(g.user_id).get()
        total_count = len(follower_ids)

        # 分页
        page_followings = follower_ids[(page - 1) * per_page:page * per_page]
        # 遍历获取缓存信息
        results = []
        for following_user_id in page_followings:
            user = UserProfileCache(following_user_id).get()
            # 判断我有没有关注这个粉丝
            from cache.user import UserFollowingCache
            mutual_follow = UserFollowingCache(g.user_id).user_follows_target(user.get('id'))
            results.append({
                'id': following_user_id,
                'name': user.get('name'),
                'photo': user.get('photo'),
                'mutual_follow': mutual_follow
            })

        return {'total_count': total_count, 'page': page, 'per_page': per_page, 'results': results}